package program;

import gamecomponents.settings.GameSettings;
import gamemodels.IGameModel;
import gamemodels.WorldModel;
import input.InputManager;

import java.awt.AWTException;
import java.awt.Canvas;

import view.View;

/**
 * Game main controller. Runs the model, provides the inputhandler.
 * @author Team Deer
 * 
 */
public class GameController {
	private static int millisecondsPerFrame = GameSettings.MS_PER_FRAME;
	private static InputManager inputManager;

	/**
	 * 
	 * @param fps
	 *            - Sets the fps
	 */
	public static void setTargetFramePerSecond(final int fps) {
		GameController.millisecondsPerFrame = (1000 / fps);
	}

	/**
	 * 
	 * @return Frames per second
	 */
	public static int getTargetFramePerSecond() {
		return 1000 / millisecondsPerFrame;
	}

	/**
	 * Add an input manager that listens to the specified canvas
	 * 
	 * @param canvas
	 *            - The canvas to listen to
	 * @throws AWTException
	 *             - If a Robot can't be created in InputManager()
	 */
	public static void addInputManager(final Canvas canvas) throws AWTException {
		inputManager = new InputManager(canvas.getGraphicsConfiguration()
				.getDevice());
		canvas.addMouseMotionListener(inputManager);
		canvas.addMouseListener(inputManager);
		canvas.addKeyListener(inputManager.getKeyboardState());
		canvas.requestFocus();

	}

	/**
	 * 
	 * @return the input manager
	 */
	public static InputManager getInputManager() {
		return inputManager;
	}

	/**
	 * Runs the specified model.
	 * 
	 * @param model
	 *            - the model to run
	 */
	public static void run(IGameModel model) {
		try {
			while (model.isRunning()) {
				// If there a new model should be runned run it instead
				if (model.getNextModel() != null) {
					model = model.getNextModel();
					model.reset();
					GameController.loadView(model);
				}
				// if you have alt-tabbed to another window the model should not
				// be updated
				if (View.getInstance().getCanvas().isFocusOwner()) {
					model.update(inputManager);
					inputManager.getKeyboardState()
							.updatePreviousKeyboardState();
				}
				Thread.sleep(millisecondsPerFrame);
			}
		} catch (final InterruptedException e) {
			// Thread should be killed. Do nothing.
		}

	}

	private static void loadView(IGameModel model) {
		View.getInstance().load(model);
		/*
		 * If the model represents a gameplay in a game world you have to hide
		 * the mouse
		 */
		if (model instanceof WorldModel) {
			inputManager.resetMousePosition();
			// Hide the cursor
			View.getInstance().setCursor(GameSettings.transparentCursor);
		} else {
			View.getInstance().setCursor(null);
		}
	}
}
